#include "StdAfx.h"
#include "UIContainer.h"

/////////////////////////////////////////////////////////////////////////////////////
//
//

CContainerUI::CContainerUI() : 
   m_hwndScroll(NULL), 
   m_iPadding(0),
   m_iScrollPos(0),
   m_bAutoDestroy(true) {
   m_cxyFixed.cx = m_cxyFixed.cy = 0;
   ::ZeroMemory(&m_rcInset, sizeof(m_rcInset));
}

CContainerUI::~CContainerUI() {
   RemoveAll();
}

LPCTSTR CContainerUI::GetClass() const {
   return _T("ContainerUI");
}

LPVOID CContainerUI::GetInterface(LPCTSTR pstrName) {
	if (_tcscmp(pstrName, _T("Container")) == 0) {
		return static_cast<IContainerUI*>(this);
	}
	return CControlUI::GetInterface(pstrName);
}

bool CContainerUI::Add(CControlUI* pControl) {
	if (m_pManager != NULL) {
		m_pManager->InitControls(pControl, this);
	}
	if (m_pManager != NULL) {
		m_pManager->UpdateLayout();
	}
	return m_items.Add(pControl);
}

bool CContainerUI::Remove(CControlUI* pControl) {
	for ( int it = 0; m_bAutoDestroy && it < m_items.GetSize(); it++ ) {
		if ( static_cast<CControlUI*>(m_items[it]) == pControl ) {
			if (m_pManager != NULL) {
				m_pManager->UpdateLayout();
			}
			delete pControl;
			return m_items.Remove(it);
		}
	}
	return false;
}

void CContainerUI::RemoveAll() {
	for (int it = 0; m_bAutoDestroy && it < m_items.GetSize(); it++) {
		delete static_cast<CControlUI*>(m_items[it]);
	}
	m_items.Empty();
	m_iScrollPos = 0;
	if (m_pManager != NULL) {
		m_pManager->UpdateLayout();
	}
}

void CContainerUI::SetAutoDestroy(bool bAuto) {
   m_bAutoDestroy = bAuto;
}

void CContainerUI::SetPadding(int iPadding) {
   m_iPadding = iPadding;
}

void CContainerUI::SetWidth(int cx) {
   m_cxyFixed.cx = cx;
}

void CContainerUI::SetHeight(int cy) {
   m_cxyFixed.cy = cy;
}

void CContainerUI::Event(TEventUI& event) {
   if( m_hwndScroll != NULL ) {
      if( event.Type == UIEVENT_VSCROLL ) {
      }
   }
   CControlUI::Event(event);
}

void CContainerUI::SetPos(RECT rc) {
   CControlUI::SetPos(rc);
   if (m_items.IsEmpty()) {
	   return;
   }
   rc.left += m_rcInset.left;
   rc.top += m_rcInset.top;
   rc.right -= m_rcInset.right;
   rc.bottom -= m_rcInset.bottom;
   // We'll position the first child in the entire client area.
   // Do not leave a container empty.
   ASSERT(m_items.GetSize()==1);
   static_cast<CControlUI*>(m_items[0])->SetPos(rc);
}

void CContainerUI::SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue) {
   if ( _tcscmp(pstrName, _T("padding")) == 0 ) SetPadding(_ttoi(pstrValue));
   else if ( _tcscmp(pstrName, _T("width")) == 0 ) SetWidth(_ttoi(pstrValue));
   else if ( _tcscmp(pstrName, _T("height")) == 0 ) SetHeight(_ttoi(pstrValue));
   else CControlUI::SetAttribute(pstrName, pstrValue);
}

void CContainerUI::SetManager(CPaintManagerUI* pManager, CControlUI* pParent) {
   for ( int it = 0; it < m_items.GetSize(); it++ ) {
      static_cast<CControlUI*>(m_items[it])->SetManager(pManager, this);
   }
   CControlUI::SetManager(pManager, pParent);
}

CControlUI* CContainerUI::FindControl(FINDCONTROLPROC Proc, LPVOID pData, UINT uFlags) {
   // Check if this guy is valid
	if ((uFlags & UIFIND_VISIBLE) != 0 && !IsVisible()) {
		return NULL;
	}
	if ((uFlags & UIFIND_ENABLED) != 0 && !IsEnabled()) {
		return NULL;
	}
	if ((uFlags & UIFIND_HITTEST) != 0 && !::PtInRect(&m_rcItem, *(static_cast<LPPOINT>(pData)))) {
		return NULL;
	}
    if ( (uFlags & UIFIND_ME_FIRST) != 0 ) {
        CControlUI* pControl = CControlUI::FindControl(Proc, pData, uFlags);
        if ( pControl != NULL ) {
            return pControl;
        }
    }
    for ( int it = 0; it != m_items.GetSize(); it++ ) {
        CControlUI* pControl = static_cast<CControlUI*>(m_items[it])->FindControl(Proc, pData, uFlags);
        if (pControl != NULL) {
            return pControl;
        }
    }
    return CControlUI::FindControl(Proc, pData, uFlags);
}

void CContainerUI::DoPaint(HDC hDC, const RECT& rcPaint) {
   RECT rcTemp = { 0 };
   if( !::IntersectRect(&rcTemp, &rcPaint, &m_rcItem) ) return;

   CRenderClip clip;
   CBlueRenderEngineUI::GenerateClip(hDC, m_rcItem, clip);

   for( int it = 0; it < m_items.GetSize(); it++ ) {
      CControlUI* pControl = static_cast<CControlUI*>(m_items[it]);
      if( !pControl->IsVisible() ) continue;
      if( !::IntersectRect(&rcTemp, &rcPaint, &pControl->GetPos()) ) continue;
      if( !::IntersectRect(&rcTemp, &m_rcItem, &pControl->GetPos()) ) continue;
      pControl->DoPaint(hDC, rcPaint);
   }
}

/////////////////////////////////////////////////////////////////////////////////////
//
//

CDialogLayoutUI::CDialogLayoutUI() : m_bFirstResize(true), m_aModes(sizeof(STRETCHMODE)) {
   ::ZeroMemory(&m_rcDialog, sizeof(m_rcDialog));
}

LPCTSTR CDialogLayoutUI::GetClass() const {
   return _T("DialogLayoutUI");
}

LPVOID CDialogLayoutUI::GetInterface(LPCTSTR pstrName) {
   if( _tcscmp(pstrName, _T("DialogLayout")) == 0 ) return this;
   return CContainerUI::GetInterface(pstrName);
}

void CDialogLayoutUI::SetPos(RECT rc) {
   m_rcItem = rc;
   /*
   // RecalcArea();
   if( m_hwndScroll != NULL ) rc.right -= m_pManager->GetSystemMetrics().cxvscroll;
   // Determine how "scaled" the dialog is compared to the original size
   int cxDiff = (rc.right - rc.left) - (m_rcDialog.right - m_rcDialog.left);
   int cyDiff = (rc.bottom - rc.top) - (m_rcDialog.bottom - m_rcDialog.top);
   if( cxDiff < 0 ) cxDiff = 0;
   if( cyDiff < 0 ) cyDiff = 0;
   */
   // Stretch each control
   // Controls are coupled in "groups", which determine a scaling factor.
   // A "line" indicator is used to apply the same scaling to a new group of controls.
   /*
   int nCount, cxStretch, cyStretch, cxMove, cyMove;
   for( int i = 0; i < m_aModes.GetSize(); i++ ) {
      STRETCHMODE* pItem = static_cast<STRETCHMODE*>(m_aModes[i]);
      if ( i == 0 || (pItem->uMode & UISTRETCH_NEWGROUP) != 0 ) {
         nCount = 0;
         for ( int j = i + 1; j < m_aModes.GetSize(); j++ ) {
            STRETCHMODE* pNext = static_cast<STRETCHMODE*>(m_aModes[j]);
			if ((pNext->uMode & (UISTRETCH_NEWGROUP | UISTRETCH_NEWLINE)) != 0) {
				break;
			}
			if ((pNext->uMode & (UISTRETCH_SIZE_X | UISTRETCH_SIZE_Y)) != 0) {
				nCount++;
			}
         }
		 if (nCount == 0) {
			 nCount = 1;
		 }
         cxStretch = cxDiff / nCount;
         cyStretch = cyDiff / nCount;
         cxMove = 0;
         cyMove = 0;
      }
      if ( (pItem->uMode & UISTRETCH_NEWLINE) != 0 ) {
         cxMove = 0;
         cyMove = 0;
      }
      RECT rcPos = pItem->rcItem;
      ::OffsetRect(&rcPos, rc.left, rc.top - m_iScrollPos);
	  if ((pItem->uMode & UISTRETCH_MOVE_X) != 0) {
		  ::OffsetRect(&rcPos, cxMove, 0);
	  }
	  if ((pItem->uMode & UISTRETCH_MOVE_Y) != 0) {
		  ::OffsetRect(&rcPos, 0, cyMove);
	  }
	  if ((pItem->uMode & UISTRETCH_SIZE_X) != 0) {
		  rcPos.right += cxStretch;
	  }
	  if ((pItem->uMode & UISTRETCH_SIZE_Y) != 0) {
		  rcPos.bottom += cyStretch;
	  }
      if( (pItem->uMode & (UISTRETCH_SIZE_X | UISTRETCH_SIZE_Y)) != 0 ) {
         cxMove += cxStretch;
         cyMove += cyStretch;
      }
      pItem->pControl->SetPos(rcPos);
   }
   */
}

/*
void CDialogLayoutUI::RecalcArea() {
   if ( !m_bFirstResize ) return;
   // Add the remaining control to the list
   // Controls that have specific stretching needs will define them in the XML resource
   // and by calling SetStretchMode(). Other controls needs to be added as well now...
   for ( int it = 0; it < m_items.GetSize(); it++ ) {         
      CControlUI* pControl = static_cast<CControlUI*>(m_items[it]);
      bool bFound = false;
      for ( int i = 0; !bFound && i < m_aModes.GetSize(); i++ ) {
		  if (static_cast<STRETCHMODE*>(m_aModes[i])->pControl == pControl) {
			  bFound = true;
		  }
      }
      if ( !bFound ) {
         STRETCHMODE mode;
         mode.pControl = pControl;
         mode.uMode = UISTRETCH_NEWGROUP;
         mode.rcItem = pControl->GetPos();
         m_aModes.Add(&mode);
      }
   }
   // Figure out the actual size of the dialog so we can add proper scrollbars later
   CRect rcDialog(9999, 9999, 0,0);
   for ( int i = 0; i < m_items.GetSize(); i++ ) {
      const RECT& rcPos = static_cast<CControlUI*>(m_items[i])->GetPos();
      rcDialog.Join(rcPos);
   }
   for ( int j = 0; j < m_aModes.GetSize(); j++ ) {
      RECT& rcPos = static_cast<STRETCHMODE*>(m_aModes[j])->rcItem;
      ::OffsetRect(&rcPos, -rcDialog.left, -rcDialog.top);
   }
   m_rcDialog = rcDialog;
   // We're done with initialization
   m_bFirstResize = false;
}
*/